package com.hly.tool.task;

import com.hly.tool.constants.Constants;
import com.hly.tool.constants.HConstants;
import com.hly.tool.list.ListUtil;
import com.hly.tool.login.ContextLoginUtil;
import com.hly.tool.object.HDomainObject;
import com.hly.tool.relationship.RelationshipUtil;
import com.hly.tool.tree.EnoviaTree;
import com.matrixone.apps.domain.DomainConstants;
import com.matrixone.apps.domain.DomainObject;
import com.matrixone.apps.domain.util.FrameworkException;
import com.matrixone.apps.domain.util.MapList;
import com.matrixone.apps.domain.util.MqlUtil;
import com.matrixone.apps.domain.util.PersonUtil;
import com.matrixone.apps.framework.ui.UIUtil;
import com.matrixone.apps.program.Task;
import matrix.db.Context;
import matrix.db.JPO;
import matrix.util.MatrixException;
import matrix.util.StringList;

import java.util.*;

public class WBSTaskUtil
{


    /**
     * @param context
     * @param templatedId
     * @return
     */
    public static MapList getTemplatedTask(Context context, String templatedId)
    {
        MapList result = new MapList();
        try
        {
            DomainObject domainObject = DomainObject.newInstance(context, templatedId);
            result = HDomainObject.getRelatedObjectsAttr(context, domainObject, Constants.type_TaskManagement, Constants.rel_Subtask, HConstants.busList, HConstants.relList, false, true, (short) 1);
        } catch (Exception e)
        {
            e.printStackTrace();
        }
        return result;
    }


    /**
     * 通过WBS任务的id 获取项目号的Id
     *
     * @param context
     * @param objectId
     * @return
     * @throws Exception
     */
    public static String getProjectIdByTaskId(Context context, String objectId) throws Exception
    {
        String projectId = "";
        try
        {
//            String queryMql = "print bus Task  T-000000001  31623720784060 select to[Project Access Key].from.from[Project Access List].to.id dump |";
            StringBuffer buffer = new StringBuffer();
            buffer.append("print bus ");
            buffer.append(objectId);
            buffer.append(" select to[");
            buffer.append(" $1 ");
            buffer.append("].from.from[");
            buffer.append(" $2 ");
            buffer.append("].to.id dump |");

            projectId = MqlUtil.mqlCommand(context, buffer.toString(), Constants.rel_ProjectAccessKey, Constants.rel_ProjectAccessList);

        } catch (MatrixException e)
        {
            e.printStackTrace();
        }
        return projectId;
    }

    /**
     * 通过WBS任务的id 获取项目号的Id
     *
     * @param context
     * @param taskObject
     * @return
     * @throws Exception
     */
    public static String getProjectIdByTask(Context context, DomainObject taskObject) throws Exception
    {
        return getProjectIdByTaskId(context, taskObject.getObjectId(context));
    }


    /**
     * @param context
     * @param parentId
     * @param nodeName
     * @return String
     * @Author HLY
     * @CreateTime 2022/9/30
     * @Description: 通过子节点的名称，获取子节点的id
     */

    public static String getTaskNodeId(Context context, String parentId, String nodeName) throws Exception
    {
        //parent task
        DomainObject parentNode = DomainObject.newInstance(context, parentId);
        StringList busList = new StringList();
        busList.add(DomainConstants.SELECT_ID);
        busList.add(DomainConstants.SELECT_NAME);
        StringList relList = new StringList();
        String strWhere = "name=='" + nodeName + "'";
//        MapList childrenNode = parentNode.getRelatedObjects(context, Constants.rel_Subtask, Constants.type_TaskManagement, busList, relList, false, true, (short) 1, strWhere, null);
        MapList childrenNode = HDomainObject.getRelatedObjectsAttr(context, parentNode, Constants.type_TaskManagement, Constants.rel_Subtask, busList, relList, false, true, (short) 1, strWhere, null);

        String result = "";
        if (childrenNode.size() > 0)
        {
            Map map0 = (Map) childrenNode.get(0);
            result = (String) map0.get("id");
        }
        return result;
    }

    /**
     * @param context
     * @param parentId
     * @param nodeName
     * @return String
     * @Author HLY
     * @CreateTime 2022/9/30
     * @Description: 通过子节点的名称，获取子节点的id集合
     */

    public static List<String> getTaskNodeIds(Context context, String parentId, String nodeName) throws Exception
    {
        List<String> idList = new ArrayList<>();
        DomainObject parentNode = DomainObject.newInstance(context, parentId);
        StringList busList = new StringList();
        busList.add(DomainConstants.SELECT_ID);
        busList.add(DomainConstants.SELECT_NAME);
        StringList relList = new StringList();
        String strWhere = "name=='" + nodeName + "'";
//        MapList childrenNode = parentNode.getRelatedObjects(context, Constants.rel_Subtask, Constants.type_TaskManagement, busList, relList, false, true, (short) 1, strWhere, null);
        MapList childrenNode = HDomainObject.getRelatedObjectsAttr(context, parentNode, Constants.type_TaskManagement, Constants.rel_Subtask, busList, relList, false, true, (short) 1, strWhere, null);

        if (childrenNode.size() > 0)
        {
            idList = ListUtil.getIdList(childrenNode);
        }
        return idList;
    }

    /**
     * @param context
     * @param parentId
     * @param where
     * @return String
     * @Author HLY
     * @CreateTime 2022/9/30
     * @Description: 通过子节点的名称，获取子节点的id
     */

    public static String getTaskNodeId(Context context, String parentId, StringList busList, String where) throws Exception
    {
        //parent task
        DomainObject parentNode = DomainObject.newInstance(context, parentId);
//        StringList busList = new StringList();
//        busList.add(DomainConstants.SELECT_ID);
//        busList.add(DomainConstants.SELECT_NAME);
//        StringList relList = new StringList();
//        String strWhere = "name=='" + nodeName + "'";
//        MapList childrenNode = parentNode.getRelatedObjects(context, Constants.rel_Subtask, Constants.type_TaskManagement, busList, relList, false, true, (short) 1, strWhere, null);
        MapList childrenNode = HDomainObject.getRelatedObjectsAttr(context, parentNode, Constants.type_TaskManagement, Constants.rel_Subtask, busList, null, false, true, (short) 1, where, null);

        String result = "";
        if (childrenNode.size() > 0)
        {
            Map map0 = (Map) childrenNode.get(0);
            result = (String) map0.get("id");
        }
        return result;
    }


    /**
     * @param context
     * @param taskMap 创建WBS计划使用到的参数
     * @return String 新建 task 的id
     * @Author HLY
     * @CreateTime 2022/9/30
     * @Description:
     */

    public static String getNewTaskNodeId(Context context, Map taskMap) throws Exception
    {
        return getNewTaskNodeId(context, taskMap, null);
    }

    /**
     * @param context
     * @param taskMap    创建WBS计划使用到的参数
     * @param cusAttrMap 扩展属性的参数
     * @return String 新建 task 的id
     * @Author HLY
     * @CreateTime 2022/9/30
     * @Description:
     */

    public static String getNewTaskNodeId(Context context, Map taskMap, Map cusAttrMap) throws Exception
    {
        Map task = createTask(context, taskMap);
        String id = (String) task.get("id");
        if (cusAttrMap != null && !cusAttrMap.isEmpty())
        {
            DomainObject taskObj = DomainObject.newInstance(context, id);
            taskObj.setAttributeValues(context, cusAttrMap);
        }
        return id;
    }

    /**
     * @param context
     * @param taskMap    创建WBS计划使用到的参数
     * @param cusAttrMap 扩展属性的参数
     * @return DomainObject 新建 task 的对象
     * @Author HLY
     * @CreateTime 2022/9/30
     * @Description:
     */

    public static DomainObject getNewTaskNodeObj(Context context, Map taskMap, Map cusAttrMap) throws Exception
    {
        DomainObject taskObj = null;
        Map task = createTask(context, taskMap);
        String id = (String) task.get("id");
        if (cusAttrMap != null && !cusAttrMap.isEmpty())
        {
            taskObj = DomainObject.newInstance(context, id);
            taskObj.setAttributeValues(context, cusAttrMap);
        }

        return taskObj;
    }


    /**
     * get create task map
     *
     * @param parentOID
     * @return
     */
    public static Map getTaskMap(String parentOID)
    {

        //create task
        Map taskMap = new HashMap();
        taskMap.put("objectId", parentOID);
        taskMap.put("parentId", parentOID);
        taskMap.put("addTask", "addTaskBelow");
        taskMap.put("InsertAboveBelow", "addTaskBelow");
        taskMap.put("autoNameCheck", "true");
        taskMap.put("TypeActual", "Task");
        taskMap.put("Policy", "Project Task");
        taskMap.put("OwnerOID", "");
        taskMap.put("Description", "");
        taskMap.put("AssigneeOID", "");
        taskMap.put("TaskRequirement", "Optional");
        taskMap.put("ProjectRole", "");
        taskMap.put("Calendar", "");
        taskMap.put("TaskConstraintDate", "");
        taskMap.put("Task Constraint Type", "As Soon As Possible");
        taskMap.put("DurationKeywords", "");
        taskMap.put("Duration", "1");
        taskMap.put("units_Duration", "d");
        taskMap.put("DeliverableOID", "");
        taskMap.put("NumberOf", "1");
        taskMap.put("NeedsReview", "No");
        taskMap.put("Name", "");
        return taskMap;

    }

    /**
     * get create task map
     *
     * @param fieldMap
     * @return
     */
    public static Map getTaskMap(Map fieldMap)
    {

        //create task
        Map taskMap = new HashMap();
        taskMap.put("objectId", "");
        taskMap.put("parentId", "");
        taskMap.put("addTask", "addTaskBelow");
        taskMap.put("InsertAboveBelow", "addTaskBelow");
        taskMap.put("autoNameCheck", "");
        taskMap.put("TypeActual", "Task");
        taskMap.put("Policy", "Project Task");
        taskMap.put("OwnerOID", "");
        taskMap.put("Description", "");
        taskMap.put("AssigneeOID", "");
        taskMap.put("TaskRequirement", "Optional");
        taskMap.put("ProjectRole", "");
        taskMap.put("Calendar", "");
        taskMap.put("TaskConstraintDate", "");
        taskMap.put("Task Constraint Type", "As Soon As Possible");
        taskMap.put("DurationKeywords", "");
        taskMap.put("Duration", "1");
        taskMap.put("units_Duration", "d");
        taskMap.put("DeliverableOID", "");
        taskMap.put("NumberOf", "1");
        taskMap.put("NeedsReview", "No");
        taskMap.put("Name", "");
        if (fieldMap != null)
        {
            taskMap.putAll(fieldMap);
        }


        return taskMap;

    }

    /**
     * get create task map
     *
     * @param parentOID
     * @return
     */
    public static Map getTaskMap(String parentOID, String Name)
    {
        //create task
        Map taskMap = new HashMap();
        taskMap.put("objectId", parentOID);
        taskMap.put("parentId", parentOID);
        taskMap.put("addTask", "addTaskBelow");
        taskMap.put("InsertAboveBelow", "addTaskBelow");
        taskMap.put("autoNameCheck", null);
        taskMap.put("TypeActual", "Task");
        taskMap.put("Policy", "Project Task");
        taskMap.put("OwnerOID", "");
        taskMap.put("Description", "");
        taskMap.put("AssigneeOID", "");
        taskMap.put("TaskRequirement", "Optional");
        taskMap.put("ProjectRole", "");
        taskMap.put("Calendar", "");
        taskMap.put("TaskConstraintDate", "");
        taskMap.put("Task Constraint Type", "As Soon As Possible");
        taskMap.put("DurationKeywords", "");
        taskMap.put("Duration", "1");
        taskMap.put("units_Duration", "d");
        taskMap.put("DeliverableOID", "");
        taskMap.put("NumberOf", "1");
        taskMap.put("NeedsReview", "No");
        taskMap.put("Name", Name);

        return taskMap;

    }


    /**
     * create task
     *
     * @param context
     * @param taskMap
     * @return
     * @throws Exception
     * @throws Exception
     */
    public static Map createTask(Context context, Map taskMap) throws Exception
    {
        //System.out.println("taskMap = " + taskMap);
        String[] args = JPO.packArgs(taskMap);
        Map invoke = JPO.invoke(context, "emxTask", null, "createNewTask", args, Map.class);
        return invoke;
    }


    /**
     * 获取WBS 任务下的配分配人员
     *
     * @param context
     * @param task
     * @return
     */
    public static MapList getAssignees(Context context, Task task)
    {
        MapList result = new MapList();
        try
        {
            StringList busList = new StringList();
            StringList relList = new StringList();
            busList.add(DomainConstants.SELECT_ID);
            busList.add(DomainConstants.SELECT_TYPE);
            busList.add(DomainConstants.SELECT_NAME);

            List<String> relationshipAttrNames = RelationshipUtil.getRelationshipAttrNames(context, Constants.rel_AssignedTasks);
            for (int i = 0; i < relationshipAttrNames.size(); i++)
            {
                String attrName = relationshipAttrNames.get(i);
                relList.add("attribute[" + attrName + "]");
            }
            result = task.getAssignees(context, busList, relList, DomainConstants.EMPTY_STRING);
        } catch (FrameworkException e)
        {
            e.printStackTrace();
        }

        return result;
    }


    /**
     * 获取WBS 任务下的配分配人员
     *
     * @param context
     * @param objectId
     * @return
     */
    public static MapList getAssignees(Context context, String objectId) throws FrameworkException
    {
        Task task = new Task(DomainObject.newInstance(context, objectId));
        return getAssignees(context, task);
    }


    /**
     * 获取WBS 任务下的配分配人员
     *
     * @param context
     * @param taskObj
     * @return
     */
    public static MapList getAssignees(Context context, DomainObject taskObj) throws FrameworkException
    {
        Task task = new Task(taskObj);
        return getAssignees(context, task);
    }


    /**
     * 获取WBS 任务下的配分配人员中角色是任务委托人的集合
     *
     * @param context
     * @param task
     * @return
     */
    public static MapList getRelAssignees(Context context, Task task)
    {
        MapList result = new MapList();
        MapList assignees = getAssignees(context, task);
        result = ListUtil.getMapListByAttrValue(assignees, Constants.attr_AssigneeRole, "Task Assignee");
        return result;
    }


    /**
     * 获取WBS 任务下的配分配人员中角色是任务委托人的集合
     *
     * @param context
     * @param objectId
     * @return
     */
    public static MapList getRelAssignees(Context context, String objectId) throws FrameworkException
    {
        Task task = new Task(DomainObject.newInstance(context, objectId));
        return getAssignees(context, task);
    }


    /**
     * 获取WBS 任务下的配分配人员中角色是任务委托人的集合
     *
     * @param context
     * @param taskObj
     * @return
     */
    public static MapList getRelAssignees(Context context, DomainObject taskObj) throws FrameworkException
    {
        Task task = new Task(taskObj);
        return getAssignees(context, task);
    }

    /**
     * @param context
     * @param mapList
     * @param levelMap     levelMap 需要有几个参数的值     parentKey, parentKeyVal, childKey,  parentOID
     *                     parentKey是 mapList.map中父节点外键、 parentKeyVal外键值集合、  childKey主键、 parentOID 3DE中父节点id
     * @param basicMapping 基础属性的映射关系 name type owner desciption等
     * @param attrMapping  属性的映射关系
     * @return void
     * @Author HLY
     * @CreateTime 2022/9/30
     * @Description:
     */

    public static void createTasks(Context context, MapList mapList, Map levelMap, Map basicMapping, Map attrMapping) throws Exception
    {

//        String parentKeyVal, String parentKey, String childKey, String parentOID
        StringList parentKeyVals = (StringList) levelMap.get("parentKeyVals");
        String parentKey = (String) levelMap.get("parentKey");
//        String childKey = (String) levelMap.get("childKey");
        String parentOID = (String) levelMap.get("parentOID");

        //顶层的数据集合
        MapList topList = EnoviaTree.getTopList(mapList, parentKey, parentKeyVals);

        //存储 新建的顶层节点信息
        MapList createList = new MapList();

        //遍历和新建顶层数据
        for (int i = 0; i < topList.size(); i++)
        {
            //数据集合中的一行数据
            Map map_i = (Map) topList.get(i);

            Map createMap_i = createOneTask(context, map_i, levelMap, basicMapping, attrMapping, parentOID);
            createList.add(createMap_i);
        }


        //遍历新建的数据 再次新建其子节点
        for (int i = 0; i < createList.size(); i++)
        {
            Map createMap_i = (Map) createList.get(i);

            createChildTaskNode(context, mapList, levelMap, basicMapping, attrMapping, createMap_i);
        }

    }

    /**
     * @return void
     * @Author HLY
     * @CreateTime 2022/9/30
     * @Description: 递归建子节点的计划
     */

    public static void createChildTaskNode(Context context, MapList mapList, Map levelMap, Map basicMapping, Map attrMapping, Map createMap) throws Exception
    {

        //新建的父节点
        String parentId = (String) createMap.get("id");

        //新建的父节点在子节点数据中的外键
        String childKeyVal = (String) createMap.get("childKeyVal");

        //子节点数据中的外键 的 key
        String parentKey = (String) levelMap.get("parentKey");

        //存储 再次新建的所有子节点的数据
        MapList childList = new MapList();

        //遍历匹配数据
        for (int i = 0; i < mapList.size(); i++)
        {
            Map map_i = (Map) mapList.get(i);
            String parentKeyVal_i = (String) map_i.get(parentKey);

            //匹配成功 新建子节点
            if (parentKeyVal_i.equals(childKeyVal))
            {
                //新建子节点信息 id 和 主键
                Map createMap_i = createOneTask(context, map_i, levelMap, basicMapping, attrMapping, parentId);

                //存储新建子节点信息
                childList.add(createMap_i);
            }
        }


        //遍历所有的子节点 递归新建下一层数据
        for (int i = 0; i < childList.size(); i++)
        {
            Map createMap_i = (Map) childList.get(i);

            //新建下一层数据
            createChildTaskNode(context, mapList, levelMap, basicMapping, attrMapping, createMap_i);
        }

    }


    /**
     * @param context
     * @param map
     * @param levelMap
     * @param basicMapping
     * @param attrMapping
     * @param parentOID
     * @return Map
     * @Author HLY
     * @CreateTime 2022/9/30
     * @Description: 新建计划
     */

    private static Map createOneTask(Context context, Map map, Map levelMap, Map basicMapping, Map attrMapping, String parentOID) throws Exception
    {
        Map result = new HashMap();


        String childKey = (String) levelMap.get("childKey");

        // map_i 中的自定义的属性
        Map cusAttrMap = getAttrMap(map, attrMapping);

        // map_i 中的自定义的属性
        Map basicMap = getBasicMap(context, map, basicMapping);

        //新建计划用到的 map
        basicMap.put("objectId ", parentOID);
        basicMap.put("parentId ", parentOID);
        Map taskMap = getTaskMap(basicMap);

        String newTaskId = getNewTaskNodeId(context, taskMap);

        DomainObject taskObj = DomainObject.newInstance(context, newTaskId);
        taskObj.setAttributeValues(context, cusAttrMap);

        String childKeyVal = (String) map.get(childKey);

        result.put("id", newTaskId);
        result.put("childKeyVal", childKeyVal);

        return result;

    }

    /**
     * @param map
     * @param basicMapping
     * @return Map
     * @Author HLY
     * @CreateTime 2022/9/30
     * @Description: 获取数据中的基础属性
     */
    private static Map getBasicMap(Context context, Map map, Map basicMapping) throws FrameworkException
    {
        Map basicMap = new HashMap();
        Set keySet = map.keySet();
        Iterator iterator = keySet.iterator();
        while (iterator.hasNext())
        {
            String key = (String) iterator.next();
            String attr = (String) basicMapping.get(key);
            if (UIUtil.isNotNullAndNotEmpty(attr))
            {
                String val = (String) map.get(key);
                basicMap.put(attr, val);
            }
        }


        String owner = (String) basicMap.get("owner");
        if (UIUtil.isNotNullAndNotEmpty(owner))
        {
            String OwnerOID = PersonUtil.getPersonObjectID(context, owner);
            basicMap.put("OwnerOID", OwnerOID);
        }

        String assignee = (String) basicMap.get("assignee");
        if (UIUtil.isNotNullAndNotEmpty(owner))
        {
            String AssigneeOID = PersonUtil.getPersonObjectID(context, assignee);
            basicMap.put("AssigneeOID", AssigneeOID);
        }

        return basicMap;
    }

    /**
     * @param map
     * @param attrMapping
     * @return Map
     * @Author HLY
     * @CreateTime 2022/9/30
     * @Description: 获取数据中的属性
     */
    private static Map getAttrMap(Map map, Map attrMapping)
    {
        Map attrMap = new HashMap();
        Set keySet = map.keySet();
        Iterator iterator = keySet.iterator();
        while (iterator.hasNext())
        {
            String key = (String) iterator.next();
            String attr = (String) attrMapping.get(key);
            if (UIUtil.isNotNullAndNotEmpty(attr))
            {
                String val = (String) map.get(key);
                attrMap.put(attr, val);
            }
        }
        return attrMap;
    }


    public static void main(String[] args)
    {
        try
        {
            Context context = ContextLoginUtil.getCasAdminContext("https://3dx.vs.com/3dspace/", "ctx::VPLMProjectLeader.Company Name.Common Space", "admin_platform", "Qwerty12345");
            System.out.println("context : " + context);

        } catch (Exception e)
        {
            throw new RuntimeException(e);
        }
    }
}



